﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Mail;
using System.Text.RegularExpressions;
using System.Web.Configuration;
using NLog;
using System.IO;
using System.Configuration;
using System.Net;
using planerka.Common;
using planerka.Common.Enums;
using System.Web.Mvc;

namespace planerka.DataAccess.DataService
{
    //// email result
    //public class emailOrderInfo
    //{
    //    public long? orderID_emailToAdmin { get; set; }
    //    public long? orderID_emailToClient { get; set; }
    //}

    public class EmailSMTP_Service
    {
        // Logger
        private static Logger logger = LogManager.GetCurrentClassLogger();

        // асинхронная отправка почты
        #region asynchronousEmail

        public void Callback(IAsyncResult ar) //это вызовется по окончанию отправки
        {
            RunToNextThread nextThread = (RunToNextThread)ar.AsyncState;
            bool boolResult = nextThread.EndInvoke(ar); //так получаем возвращаемое значение
        }


        public delegate bool RunToNextThread(
                    emailLoginTypes emailLoginType,
                    string toMail,
                    string bodyText,
                    string subject,
                    string ReplyTo,
                     List<SelectListItem> attachments = null, 
                     Guid? message_guid = null);

        #endregion

        // Отправка сообщений на электронную почту
        public bool ExecuteHtmlSendMail(
            emailLoginTypes emailLoginType,
            string ToAddress,
            string BodyText,
            string Subject,
            string ReplyTo = "",
            List<SelectListItem> attachments = null, // Value = filePath
            Guid? message_guid = null
            ) 
        {
            // System.Net.Mail can only send email.

            // http://www.dijksterhuis.org/using-csharp-to-send-an-e-mail-through-smtp/
            // SMTP Simple Mail Transfer Protocol
            // POP post office protocol - клиентский протокол работы с почтой , 
            // проще говоря по этому протоколу почтовый клиент забирает почту с сервера

            // SmtpClient.SendAsync Method (MailMessage, Object)
            // http://msdn.microsoft.com/en-us/library/x5x13z6h.aspx

            bool sent = false; // отправлено или нет сообщение

            string smtpHostLogin = "";
            string smtpHostPassword = "";
            string smtpHost = "";

            if (emailLoginType == emailLoginTypes.service)
            {
                smtpHostLogin = WebConfigurationManager.AppSettings["smtpHostLogin"];
                smtpHostPassword = WebConfigurationManager.AppSettings["smtpHostPassword"];
                smtpHost = WebConfigurationManager.AppSettings["smtpHost"];
            }
            else 
            {
                smtpHostLogin = WebConfigurationManager.AppSettings["smtpRouterLogin"];
                smtpHostPassword = WebConfigurationManager.AppSettings["smtpRouterPassword"];
                smtpHost = WebConfigurationManager.AppSettings["smtpRouterHost"];
            }

            if (emailIsValid(smtpHostLogin) && emailIsValid(ToAddress))
            {
                

                MailAddress from = new MailAddress(smtpHostLogin);
                if (message_guid != null)
                    from = new MailAddress(smtpHostLogin, "[" + message_guid.ToString() + "]");

                MailAddress to = new MailAddress(ToAddress);

                MailMessage mailMsg = new MailMessage(from, to);

                if (!String.IsNullOrEmpty(ReplyTo))
                {
                    mailMsg.ReplyToList.Clear();
                    mailMsg.ReplyToList.Add(new MailAddress(ReplyTo));
                }

                

                mailMsg.Subject = Subject;
                mailMsg.BodyEncoding = System.Text.Encoding.GetEncoding("utf-8");
                AlternateView plainView = System.Net.Mail.AlternateView.CreateAlternateViewFromString
                (System.Text.RegularExpressions.Regex.Replace(BodyText, @"", string.Empty), null, "text/plain");
                AlternateView htmlView = System.Net.Mail.AlternateView.CreateAlternateViewFromString(BodyText, null, "text/html");
                mailMsg.AlternateViews.Add(plainView);
                mailMsg.AlternateViews.Add(htmlView);
                mailMsg.IsBodyHtml = true;

                if (attachments != null)
                {
                    Attachment att;
                    foreach (var _attachment in attachments)
                    {
                        
                        if (System.IO.File.Exists(_attachment.Value))
                        {
                            att = new Attachment(_attachment.Value);
                            att.Name = _attachment.Text;

                            mailMsg.Attachments.Add(att);
                        }

                    }

                }

                using (SmtpClient sc = new SmtpClient())
                {
                    sc.EnableSsl = Convert.ToBoolean(WebConfigurationManager.AppSettings["EnableSsl"]);
                    sc.DeliveryMethod = SmtpDeliveryMethod.Network;
                    
                    //sc.UseDefaultCredentials = false;
                    //smtp.Port = Convert.ToInt32(WebConfigurationManager.AppSettings["smtpPort"]);

                    sc.Timeout = 200000; // ms, default value is 100000 (100 s)
                    sc.Host = smtpHost;
                    sc.Credentials = new NetworkCredential(
                       smtpHostLogin, smtpHostPassword);
                    
                    try
                    {
                        sc.Send(mailMsg);
                        sent = true;
                    }
                    catch (Exception ex)
                    {
                        sent = false;
                        ExceptionUtility.LogException(logger, ex, "public bool ExecuteHtmlSendMail(...)",
                             "Ошибка отправки почты. From: " + smtpHostLogin + ", To: " + ToAddress + ". Subject: " + Subject);
                        
                    }
                }
            }

            return sent;
        }

        // Notify System Operators about an exception
        public static void NotifySystemEvents
            (Exception exc, 
            string message, 
            bool sendToIT = true)
        {
            // Include code for notifying IT system operators
            EmailSMTP_Service _emailService = new EmailSMTP_Service();

            string fromMail = ConfigurationManager.AppSettings["smtpHostLogin"];

            string toAddress;
            if (sendToIT)
                toAddress = ConfigurationManager.AppSettings["sendToIT"];
            else
                toAddress = ConfigurationManager.AppSettings["sendToAdministrator"];

            string mailBody = (exc != null ? exc.Message : "") + "<br />" + message;
            // отправим почту клиенту
            try
            {

                EmailSMTP_Service.RunToNextThread nextThread = _emailService.ExecuteHtmlSendMail;
                //этот код будет выполнятся асинхронно и не будет останавливать основной поток
                nextThread.BeginInvoke(
                    emailLoginTypes.service,
                    toAddress,
                    mailBody,
                    sendToIT ? "Оповещение для ИТ-службы" : "Оповещение для менеджера", 
                    null, 
                    null, null, 
                    _emailService.Callback,
                    nextThread);

            }
            catch (Exception ex)
            {
                ExceptionUtility.LogException(logger, ex, "public static void NotifySystemEvents(Exception exc, string message, bool sendToIT = true)",
                    "Ошибка отправки почты");
                    
            }
        }

        // адрес электронной почты - в правильном формате?
        public static bool emailIsValid(string email)
        {
            Regex reg = new Regex(@"\w+([-_+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*");
            //Regex reg = new Regex(@"^[A-Za-z0-9](([_\.\-]?[a-zA-Z0-9]+)*)@([A-Za-z0-9]+)(([\.\-]?[a-zA-Z0-9]+)*)\.([A-Za-z]{2,})$");
            return reg.IsMatch(email ?? "");
        }
    }
}
